/***************************************************************************
 *   Copyright (C) 2006 by Autostop team                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

///@file autopackets.h Defiitiona of packets used by pcnetlib

#ifndef AUTOPACKETS_H
#define AUTOPACKETS_H



// Qt
#include <QHostAddress>

// gnet
#include "gnetpackets.h"

// gparams
#include "gparams.h"

// libanalyzer
#include "analyzer.h"    // for pimage_t 




typedef struct _objectCoordinates
{
	QRect          positionRect;     ///< rect describing object position
	QPoint         barycentrumPoint; ///< barycentrum position in global coordinates
	QString        description;      ///< object description
	QList< QPair< QPoint, qint16 > > trace;            ///< objects trace
} objectCoordinates;


	
struct Event
{
	quint64    id;
	quint8     type;
	QDateTime  dateTime;
	QString    message;
	QByteArray firstImage;
	QByteArray secondImage;
};



// ----------------------------- GAutoPacket ----------------------------
/// Base class for all packets
class GAutoPacket : public GNetPacket
{
	Q_OBJECT
public:

	/// Packet types
	enum PacketType
	{
		PACKET_PARAMS	= MKWORD( 'a', 'u', 't', 'o' ),	///< New param value
		
		PACKET_UDP_HOST_INFO,       ///< starts sending udp frames to specified host
		PACKET_UDP_STOP,			///< stop sending udp frames to specified address
		
		PACKET_AREAS_CONFIG,        ///< Areas configuration file (xml)
		
		PACKET_MARKERS_IMAGE,       ///< Markers image for analyzer
		PACKET_ROI_IMAGE,           ///< ROI image for analyzer
		PACKET_SHUTTER_IMAGE,       ///< Shutter image for second camera for analyzer
		
		PACKET_OBJECTS_COORDINATES, ///< Object rect with info string
		PACKET_FRAME,               ///< Default image packet
		
		PACKET_REQUEST,				///< Request for data/value
		
		PACKET_REPLY_FRAME,			///< Request reply - frame
		PACKET_REPLY_AREAS_CONFIG,  ///< Request reply - areas config file
		PACKET_REPLY_CAMERA_CONFIG, ///< Request reply - camera config file
		PACKET_REPLY_PARAMS,        ///< Request reply - params
		
		PACKET_REPLY_EVENTS,
  
		PACKET_EVENT_TRIGGER,       ///< 2nd camera trigger
		
		PACKET_UNKNOWN,				///< Unknown packet
		PACKET_LAST
	};

	// construction / destruction
	GAutoPacket() : GNetPacket() {}
	virtual ~GAutoPacket() {}

	// type query
	virtual quint64 packetType() const { return 0; }

	virtual GHeader header() const;
	static void registerPackets();

private:
}; // !GAutoPacket
// ---------------------------------------------------------------------------




// ----------------------- GAutoParams ---------------------------------------
class GAutoParams : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoParams() : GAutoPacket() {}
	virtual ~GAutoParams() {}

	static GNetPacket * createPacket() { return new GAutoParams(); }
	
	virtual quint64 packetType() const { return PACKET_PARAMS; }
	
    void setParams( const GParams & params ) { _params = params; }
    GParams params() { return _params; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
    GParams _params; ///< Params values
	
}; // ! GAutoParams
// ---------------------------------------------------------------------------




// ----------------------- GAutoAreasConfig ------------------------------------
class GAutoAreasConfig : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoAreasConfig() : GAutoPacket() {}
	virtual ~GAutoAreasConfig() {}

	static GNetPacket * createPacket() { return new GAutoAreasConfig(); }
	
	// ----------------------------------------------------
	// GAutoXmlConfig specific 	
	QByteArray data() { return _data; }
	void setData( const QByteArray & data ) { _data = data; }
	
	virtual quint64 packetType() const { return PACKET_AREAS_CONFIG; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
	QByteArray _data; ///< xml config files data 
	
}; // ! GAutoAreasConfig
// ---------------------------------------------------------------------------




// ----------------------- GAutoMarkersImage ---------------------------------
class GAutoMarkersImage : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoMarkersImage() : GAutoPacket() {}
	virtual ~GAutoMarkersImage() {}

	static GNetPacket * createPacket() { return new GAutoMarkersImage(); }
	
	// ----------------------------------------------------
	// packets specific 	
	pimage_t markersImage() { return _markersImage; }
	void setMarkersImage( const pimage_t markersImage ) { _markersImage = markersImage; }
	
	virtual quint64 packetType() const { return PACKET_MARKERS_IMAGE; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
	pimage_t _markersImage; ///< markers image
	
}; // ! GAutoMarkersImage
// ---------------------------------------------------------------------------




// ----------------------- GAutoRoiImage -------------------------------------
class GAutoRoiImage : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoRoiImage() : GAutoPacket() {}
	virtual ~GAutoRoiImage() {}

	static GNetPacket * createPacket() { return new GAutoRoiImage(); }
	
	// ----------------------------------------------------
	// packets specific 	
	pimage_t roiImage() { return _roiImage; }
	void setRoiImage( const pimage_t roiImage ) { _roiImage = roiImage; }
	
	virtual quint64 packetType() const { return PACKET_ROI_IMAGE; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
	pimage_t _roiImage; ///< roi image
	
}; // ! GAutoRoiImage
// ---------------------------------------------------------------------------




// ----------------------- GAutoShutterImage ---------------------------------
class GAutoShutterImage : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoShutterImage() : GAutoPacket() {}
	virtual ~GAutoShutterImage() {}

	static GNetPacket * createPacket() { return new GAutoShutterImage(); }
	
	// ----------------------------------------------------
	// packets specific 	
	pimage_t shutterImage() { return _shutterImage; }
	void setShutterImage( const pimage_t shutterImage ) { _shutterImage = shutterImage; }
	
	virtual quint64 packetType() const { return PACKET_SHUTTER_IMAGE; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
	pimage_t _shutterImage; ///< shutter image
	
}; // ! GAutoShutterImage
// ---------------------------------------------------------------------------




// ----------------------- GAutoObjectCoordinates ----------------------------
class GAutoObjectCoordinates : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoObjectCoordinates() : GAutoPacket() {}
	virtual ~GAutoObjectCoordinates() {}

	static GNetPacket * createPacket() { return new GAutoObjectCoordinates(); }
	
	virtual quint64 packetType() const { return PACKET_OBJECTS_COORDINATES; }
	
	// ----------------------------------------------------
	// packets specific 	
	
		
	/// Clears object list.
	void clear() { _objectsCoordinates.clear(); }
	
	/// Appends new object to objects list.
	void append( const QRect  & positionRect,
				 const QPoint & barycentrumPoint,
				 const QString & description,
				 const QList< QPair< QPoint, qint16 > > & trace
			   )
	{
		objectCoordinates object;
		
		object.positionRect     = positionRect;
		object.barycentrumPoint = barycentrumPoint;
		object.description      = description;
		qCopy( trace.begin(), trace.end(), object.trace.begin() );
		
		_objectsCoordinates.append( object );
	}
	
	/// Apends new object to objects list.
	void append( objectCoordinates object )
		{ _objectsCoordinates.append( object ); }
	
	/// Returns an object at index position \a i.
	objectCoordinates at( int i )const
		{ return _objectsCoordinates.at( i ); }
	
	/// Returns object's \e positionRect at index position \a i.
	QRectF positionRectAt( int i )const
		{ return _objectsCoordinates.at( i ).positionRect; }
	
	/// Return object's \e barycentrumPoint at index position \a i.
	QPointF barycentrumPointAt( int i )const
		{ return _objectsCoordinates.at( i ).barycentrumPoint; }
	
	/// Returns object's \e description at index position \a i.
	QString descriptionAt( int i )const
		{ return _objectsCoordinates.at( i ).description; }
	
	/// Returns object's \e trace at index position \a i.
	QList< QPair< QPoint, qint16 > > trace( int i ) const
		{ return _objectsCoordinates.at( i ).trace; }
	
	/// Return number of objects in packet.
	int size()const { return _objectsCoordinates.size(); }
	
	/// Returns the reference to \e _objectsCoordinates.
	QList<objectCoordinates> & objectsCoordinates() { return _objectsCoordinates; }
	
protected:
	virtual void writeData( QDataStream & out ) const;
	virtual void readData( QDataStream & in );
	
private:
	QList<objectCoordinates> _objectsCoordinates;
	
}; // ! GAutoObjectCoordinates
// ---------------------------------------------------------------------------




// ---------------------------- GAutoFrame ------------------------------------
class GAutoFrame : public GAutoPacket
{
	Q_OBJECT
			
public:
	GAutoFrame() : GAutoPacket(), _accelExceeded(false) {}
	virtual ~GAutoFrame() {}

	static GNetPacket * createPacket() { return new GAutoFrame(); }
	
	virtual quint64 packetType() const { return PACKET_FRAME; }
	
	// ----------------------------------------------------
	// packets specific 	
	
	enum ImageType
	{
		NO_IMAGE = 1,	///< Null image
		RAW_IMAGE, 		///< Uncomressed grayscale 8bpp image
		JPEG2K_YUV		///< Jpeg2000 codestream, YUV colorspace
	};
	
	/// Returns reference to images byteArray.
	QByteArray & image() { return _image; }
	
	/// Returns images width.
	quint16 width()const { return _width; }
	
	/// Returns images height.
	quint16 height()const { return _height; }
	
	/// Returns images type.
	ImageType type()const { return _type; }
	
	/// Returns image id
	quint32 id() const { return _id; }

	/// Returns true if accel was exceeded when frame was grabbed
	bool isAccelExceeded()const { return _accelExceeded; }
	
	/// Sets \e _image to \a image.
	void setImage( const QByteArray & image) { _image = image; }
	
	/// Sets \e _width to \a width.
	void setWidth( const quint16 width ) { _width = width; }
	
	/// Sets \e _height to \a height.
	void setHeight( const quint16 height ) { _height = height; }
	
	/// Sets \e _type to \a type.
	void setType( const ImageType type ) { _type = type; }
	
	/// Sets id
	void setId( quint32 id ) { _id = id; }

	/// Sets exceeded flag
	void setAccelExceeded( bool b ) { _accelExceeded = b; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
	ImageType	_type;   ///< images type
	quint16		_width;  ///< images width
	quint16		_height; ///< images height
	quint32		_id;	///< Image id
	QByteArray  _image;  ///< images data
	bool        _accelExceeded; ///< indicates wheather acceles was exceeded while grabbing frame
		
}; // ! GAutoFrame
// ---------------------------------------------------------------------------





// ----------------------------- GAutoRequest --------------------------------
/// Request packet - used to ask for frame
/// Each request has its unique id, whcih will be used in reply packet,
/// To associate request with packet
class GAutoRequest : public GAutoPacket
{
	Q_OBJECT
public:

	/// Request types
	enum RequestType
	{
		REQUEST_FRAME,				///< param value request
		REQUEST_AREAS_CONFIG,
		REQUEST_CAMERA_CONFIG,
		REQUEST_PARAMS,
		
		REQUEST_EVENTS,
		
		REQUEST_INVALID,
		REQUEST_LAST
	};

	// construction / destruction
	
	GAutoRequest( RequestType type = REQUEST_INVALID, uint id = -1 );
	virtual ~GAutoRequest() {}

	static GNetPacket * createPacket() { return new GAutoRequest(); }

	// request - specific
	RequestType requestType() const { return _requestType; }
	quint32 requestId() const { return _requestId; }

	virtual quint64 packetType() const { return PACKET_REQUEST; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );
	
private:

	RequestType 	_requestType;		///< Request type
	quint32			_requestId;			///< Unique request id
	
}; // !GAutoRequest
// ---------------------------------------------------------------------------




// ----------------------------- GAutoReplyFrame -----------------------------
/// Reqeust reply - frame
class GAutoReplyFrame : public GNetPacketReply
{
	Q_OBJECT
public:

	// construction / destruction
	GAutoReplyFrame( uint requestId = -1 )
		: GNetPacketReply( requestId ) {}
	virtual ~GAutoReplyFrame() {}

	static GNetPacket * createPacket() { return new GAutoReplyFrame(); }

	// packet - specific
	quint16 width()const { return _width; }
	quint16 height()const { return _height; }
	const QByteArray & image() { return _image; }
	quint64 timestamp()const { return _timestamp; }
	
	void setWidth( const quint16 width ) { _width = width; }
	void setHeight( const quint16 height ) { _height = height; }
	void setImage( const QByteArray & image ) { _image = image; }
	void setTimestamp ( const quint64 timestamp ) { _timestamp = timestamp; }
	
	virtual quint64 packetType() const { return GAutoPacket::PACKET_REPLY_FRAME; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	quint16 	_width;
	quint16 	_height;
	QByteArray	_image;
	quint64		_timestamp;
	
}; // !GAutoReplyFrame
// ---------------------------------------------------------------------------




// ----------------------- GAutoReplyParams ----------------------------------
class GAutoReplyParams : public GNetPacketReply
{
	Q_OBJECT
			
public:
	GAutoReplyParams( uint requestId = -1 ) : GNetPacketReply( requestId ) {}
	virtual ~GAutoReplyParams() {}

	static GNetPacket * createPacket() { return new GAutoReplyParams(); }
	
	virtual quint64 packetType() const { return GAutoPacket::PACKET_REPLY_PARAMS; }
	
    void setParams( const GParams & params ) { _params = params; }
    GParams params() { return _params; }
	
protected:
	virtual void writeData( QDataStream & ) const;
	virtual void readData( QDataStream & );
	
private:
    GParams _params; ///< Params values
	
}; // ! GAutoReplyParams
// ---------------------------------------------------------------------------




// ------------------------- GAutoReplyAreasConfig -----------------------------
class GAutoReplyAreasConfig : public GNetPacketReply
{
	Q_OBJECT
public:

	// construction / destruction
	GAutoReplyAreasConfig( uint requestId = -1 )
		: GNetPacketReply( requestId ) {}
	virtual ~GAutoReplyAreasConfig() {}

	static GNetPacket * createPacket() { return new GAutoReplyAreasConfig(); }

	// packet - specific
	QByteArray & data() { return _data; }
	void setData( const QByteArray & data ) { _data = data; }
	
	virtual quint64 packetType() const { return GAutoPacket::PACKET_REPLY_AREAS_CONFIG; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	QByteArray _data;
	
}; // !GAutoReplyAreasConfig
// ---------------------------------------------------------------------------




// ------------------------- GAutoReplyCameraConfig --------------------------
class GAutoReplyCameraConfig : public GNetPacketReply
{
	Q_OBJECT
public:

	// construction / destruction
	GAutoReplyCameraConfig( uint requestId = -1 )
		: GNetPacketReply( requestId ) {}
	virtual ~GAutoReplyCameraConfig() {}

	static GNetPacket * createPacket() { return new GAutoReplyCameraConfig(); }
	
	virtual quint64 packetType() const { return GAutoPacket::PACKET_REPLY_CAMERA_CONFIG; }

	// packet - specific
	QByteArray & data() { return _data; }
	void setData( const QByteArray & data ) { _data = data; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	QByteArray _data;
	
}; // !GAutoReplyCameraConfig
// ---------------------------------------------------------------------------




// -------------------------- GAutoReplyEvents{} -----------------------------
class GAutoReplyEvents : public GNetPacketReply
{
	Q_OBJECT
			
public:
	
	// construction / destruction
	GAutoReplyEvents( uint requestId = -1 ) : GNetPacketReply( requestId ) {}
	virtual ~GAutoReplyEvents() {}

	static GNetPacket * createPacket() { return new GAutoReplyEvents(); }

	virtual quint64 packetType() const { return GAutoPacket::PACKET_REPLY_EVENTS; }

	// packet - specific 
	void addEvent( const Event & event ) { _events.append( event ); }
	QList< Event > & events() { return _events; }
	
	
protected:
	// serialization

		/// Serializes object
	virtual void writeData( QDataStream & out ) const;
		/// Reads object
	virtual void readData( QDataStream & in );

private:
	QList< Event > _events;
	
};
// ---------------------------------------------------------------------------




// ------------------------------- GUDPHostInfo ------------------------------
/// Packet with host address and port for udp sender, requseting sending frames 
class GUDPHostInfo : public GAutoPacket
{
	Q_OBJECT
public:

	// construction / destruction
	GUDPHostInfo( const QHostAddress& hostAddress, quint16 port );
	GUDPHostInfo();
	virtual ~GUDPHostInfo() {}

	static GNetPacket * createPacket() { return new GUDPHostInfo(); }

	// param specific
	QHostAddress hostAddress() const { return _hostAddress; }
	quint16 port() const { return _port; }

	void setHostAddress( const QHostAddress& hostAddress ) { _hostAddress = hostAddress; }
	void setPort( bool port ) { _port = port; }

	virtual quint64 packetType() const { return PACKET_UDP_HOST_INFO; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	QHostAddress    _hostAddress;    ///< host addres
	quint16         _port;          ///< remote port 
}; // !GUDPHostInfo
// ---------------------------------------------------------------------------

// -------------------------- GUDPStopSending-------------------------------------------------
/// Request cease of sending UDP packets to specified address
class GUDPStopSending : public GUDPHostInfo
{
	Q_OBJECT
public:
	// constructon / destruction
	GUDPStopSending( const QHostAddress& hostAddress, quint16 port ):
		GUDPHostInfo( hostAddress, port ){}
	GUDPStopSending():GUDPHostInfo(){}
	
	virtual ~GUDPStopSending() {}
	
	static GNetPacket * createPacket() { return new GUDPStopSending(); }
};


// ------------------------- GAutoEventTrigger -------------------------------
class GAutoEventTrigger : public GAutoPacket
{
	Q_OBJECT
public:
	
	enum EventType
	{
		EVENT_SPEEDING,				///< Speeding
  		EVENT_REPORT,				///< Simple report
  		
		REQUEST_INVALID,
		REQUEST_LAST
	};

	
	GAutoEventTrigger( EventType eventType = REQUEST_INVALID )
		: GAutoPacket(), _eventType( eventType ) {}
	virtual ~GAutoEventTrigger() {}

	static GNetPacket * createPacket() { return new GAutoEventTrigger(); }
	
	// packet - specific
	virtual quint64 packetType() const { return PACKET_EVENT_TRIGGER; }

	EventType eventType() const { return _eventType; }
	void setEventType( const EventType eventType ) { _eventType = eventType; }
	
	/// Returns message added to event 
	QString message()const { return _message; }

	/// Sets message to the event 
	void setMessage( const QString & message ) { _message = message; }
	
	quint64 shutterTime() const { return _shutterTime; }
	quint64 sendTime() const { return _sendTime; }
	
	void setShutterTime( quint64 time ) { _shutterTime = time; }
	void setSendTime( quint64 time ) { _sendTime = time; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	EventType	_eventType;
	QString		_message;
	
	quint64		_shutterTime;	///< time when object passed shitter
	quint64		_sendTime;		///< Refernece time - time when this packet was sent
	
}; // !GAutoEventTrigger
// ---------------------------------------------------------------------------


#endif // !AUTOPACKETS_H

// eof
